package com.mygame.game_server.msgcoder;


import com.google.protobuf.GeneratedMessageV3;
import com.google.protobuf.Message;
import com.mygame.game_server.msg.GameMsgProtocol;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author Jim
 * @date 23:50 2022/5/6
 * @description 消息识别器
 * @email:huwmz04153277@126.com
 */
public final class GameMsgRecognizer {

    private static final Logger logger = LoggerFactory.getLogger(GameMsgRecognizer.class);

    /**
     * msgvaluecode字典
     */
    static private final Map<Integer, GeneratedMessageV3> _msgCodeToMsgObjMap = new ConcurrentHashMap<>();


    static private final Map<Class<?>, Integer> _msgClassToMsgCodeMap = new ConcurrentHashMap<>();

    /**
     * 初始化,根据命名规则进行反射
     */
    public static void init() {

        logger.info("========完成消息类与消息编号的映射=======");

        // 获取内部类
        Class<?>[] innerClazzArray = GameMsgProtocol.class.getDeclaredClasses();

        for (Class<?> innerClazz : innerClazzArray) {
            //判断是不是空或者这个类是不是V3子类
            if (null == innerClazz || !GeneratedMessageV3.class.isAssignableFrom(innerClazz)) {
                continue;
            }

            String clazzName = innerClazz.getSimpleName();
            clazzName = clazzName.toLowerCase();
            for (GameMsgProtocol.MsgCode msgCode : GameMsgProtocol.MsgCode.values()) {
                if (null == msgCode) {
                    continue;
                }

                String strMsgCode = msgCode.name();
                strMsgCode = strMsgCode.replaceAll("_", "").toLowerCase();
                if (!strMsgCode.startsWith(clazzName)) {
                    continue;
                }
                try {
                    // 通过反射方法创建实例
                    Object resultObj = innerClazz.getDeclaredMethod("getDefaultInstance").invoke(innerClazz);

                    logger.info("{} == {}", innerClazz.getName(), msgCode.getNumber());

                    _msgCodeToMsgObjMap.put(msgCode.getNumber(), (GeneratedMessageV3) resultObj);

                    _msgClassToMsgCodeMap.put(
                            innerClazz, msgCode.getNumber()
                    );
                } catch (Exception e) {
                    logger.error(e.getMessage(), e);
                }

            }
        }

/*        _msgCmdMap.put(GameMsgProtocol.MsgCode.USER_ENTRY_CMD_VALUE, GameMsgProtocol.UserMoveToCmd.getDefaultInstance());
        _msgCmdMap.put(GameMsgProtocol.MsgCode.WHO_ELSE_IS_HERE_CMD_VALUE, GameMsgProtocol.UserMoveToCmd.getDefaultInstance());
        _msgCmdMap.put(GameMsgProtocol.MsgCode.USER_MOVE_TO_CMD_VALUE, GameMsgProtocol.UserMoveToCmd.getDefaultInstance());


        _msgCodeMap.put(GameMsgProtocol.UserEntryResult.class, GameMsgProtocol.MsgCode.USER_ENTRY_RESULT_VALUE);
        _msgCodeMap.put(GameMsgProtocol.WhoElseIsHereResult.class, GameMsgProtocol.MsgCode.WHO_ELSE_IS_HERE_RESULT_VALUE);
        _msgCodeMap.put(GameMsgProtocol.UserMoveToResult.class, GameMsgProtocol.MsgCode.USER_MOVE_TO_RESULT_VALUE);
        _msgCodeMap.put(GameMsgProtocol.UserQuitResult.class, GameMsgProtocol.MsgCode.USER_QUIT_RESULT_VALUE);*/
    }


    private GameMsgRecognizer() {
    }

    /**
     * 获取消息构建器
     *
     * @param msgCode
     * @return
     */
    public static Message.Builder getBuilderByMsgCode(int msgCode) {
        if (msgCode < 0) {
            return null;
        }

        GeneratedMessageV3 defaultMessage = _msgCodeToMsgObjMap.get(msgCode);

        if (null == defaultMessage) {
            return null;
        } else {
            return defaultMessage.newBuilderForType();
        }

/*        if (msgCode == GameMsgProtocol.MsgCode.USER_ENTRY_CMD_VALUE) {
            return GameMsgProtocol.UserMoveToCmd.getDefaultInstance().newBuilderForType();
        } else if (msgCode == GameMsgProtocol.MsgCode.WHO_ELSE_IS_HERE_CMD_VALUE) {
            return GameMsgProtocol.WhoElseIsHereCmd.getDefaultInstance().newBuilderForType();
        } else if (msgCode == GameMsgProtocol.MsgCode.USER_MOVE_TO_CMD_VALUE) {
            return GameMsgProtocol.UserMoveToCmd.getDefaultInstance().newBuilderForType();
        } else {
            return null;
        }*/
    }

    /**
     * 根据消息类获取消息编号
     *
     * @param msgClazz
     * @return
     */
    public static int getMessageCode(Class<?> msgClazz) {
        if (null == msgClazz) {
            return -1;
        }
        if (null == _msgClassToMsgCodeMap.get(msgClazz)) {
            return -1;
        } else {
            return _msgClassToMsgCodeMap.get(msgClazz);
        }
    }
}
